{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
    "\n",
    "```shell\n",
    "pip install tensorflow-cpu\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:42.185013Z",
     "start_time": "2025-01-21T08:01:42.181175Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:34:29.349021Z",
     "iopub.status.busy": "2025-01-23T08:34:29.348669Z",
     "iopub.status.idle": "2025-01-23T08:34:29.355748Z",
     "shell.execute_reply": "2025-01-23T08:34:29.355192Z",
     "shell.execute_reply.started": "2025-01-23T08:34:29.348990Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=10, micro=14, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cu124\n",
      "cuda:0\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备\n",
    "\n",
    "https://www.kaggle.com/competitions/cifar-10/data\n",
    "\n",
    "```shell\n",
    "$ tree -L 1 cifar-10                                    \n",
    "cifar-10\n",
    "├── sampleSubmission.csv\n",
    "├── test\n",
    "├── train\n",
    "└── trainLabels.csv\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:43.186193Z",
     "start_time": "2025-01-21T08:01:42.198531Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:34:31.612958Z",
     "iopub.status.busy": "2025-01-23T08:34:31.612597Z",
     "iopub.status.idle": "2025-01-23T08:34:33.848488Z",
     "shell.execute_reply": "2025-01-23T08:34:33.847960Z",
     "shell.execute_reply.started": "2025-01-23T08:34:31.612927Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(PosixPath('competitions/cifar-10/train/1.png'), 'frog'),\n",
      " (PosixPath('competitions/cifar-10/train/2.png'), 'truck'),\n",
      " (PosixPath('competitions/cifar-10/train/3.png'), 'truck'),\n",
      " (PosixPath('competitions/cifar-10/train/4.png'), 'deer'),\n",
      " (PosixPath('competitions/cifar-10/train/5.png'), 'automobile')]\n",
      "[(PosixPath('competitions/cifar-10/test/1.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/2.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/3.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/4.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/5.png'), 'cat')]\n",
      "50000 300000\n"
     ]
    }
   ],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "DATA_DIR = Path(\".\")\n",
    "DATA_DIR1 =Path(\"competitions/cifar-10/\")\n",
    "train_lables_file = DATA_DIR / \"trainLabels.csv\"\n",
    "test_csv_file = DATA_DIR / \"sampleSubmission.csv\" #测试集模板csv文件\n",
    "train_folder = DATA_DIR1 / \"train\"\n",
    "test_folder = DATA_DIR1 / \"test\"\n",
    "\n",
    "#所有的类别\n",
    "class_names = [\n",
    "    'airplane',\n",
    "    'automobile',\n",
    "    'bird',\n",
    "    'cat',\n",
    "    'deer',\n",
    "    'dog',\n",
    "    'frog',\n",
    "    'horse',\n",
    "    'ship',\n",
    "    'truck',\n",
    "]\n",
    "\n",
    "def parse_csv_file(filepath, folder):\n",
    "    \"\"\"Parses csv files into (filename(path), label) format\"\"\"\n",
    "    results = []\n",
    "    #读取所有行\n",
    "    with open(filepath, 'r') as f:\n",
    "#         lines = f.readlines()  为什么加[1:]，可以试这个\n",
    "        #第一行不需要，因为第一行是标签\n",
    "        lines = f.readlines()[1:] \n",
    "    for line in lines:#依次去取每一行\n",
    "        image_id, label_str = line.strip('\\n').split(',')\n",
    "        image_full_path = folder / f\"{image_id}.png\"\n",
    "        results.append((image_full_path, label_str)) #得到对应图片的路径和分类\n",
    "    return results\n",
    "\n",
    "#解析对应的文件夹\n",
    "train_labels_info = parse_csv_file(train_lables_file, train_folder)\n",
    "test_csv_info = parse_csv_file(test_csv_file, test_folder)\n",
    "#打印\n",
    "import pprint\n",
    "pprint.pprint(train_labels_info[0:5])\n",
    "pprint.pprint(test_csv_info[0:5])\n",
    "print(len(train_labels_info), len(test_csv_info))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:43.217782Z",
     "start_time": "2025-01-21T08:01:43.186193Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:34:36.871063Z",
     "iopub.status.busy": "2025-01-23T08:34:36.870703Z",
     "iopub.status.idle": "2025-01-23T08:34:36.920378Z",
     "shell.execute_reply": "2025-01-23T08:34:36.919866Z",
     "shell.execute_reply.started": "2025-01-23T08:34:36.871040Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                            filepath       class\n",
      "0  competitions/cifar-10/train/1.png        frog\n",
      "1  competitions/cifar-10/train/2.png       truck\n",
      "2  competitions/cifar-10/train/3.png       truck\n",
      "3  competitions/cifar-10/train/4.png        deer\n",
      "4  competitions/cifar-10/train/5.png  automobile\n",
      "                                filepath       class\n",
      "0  competitions/cifar-10/train/45001.png       horse\n",
      "1  competitions/cifar-10/train/45002.png  automobile\n",
      "2  competitions/cifar-10/train/45003.png        deer\n",
      "3  competitions/cifar-10/train/45004.png  automobile\n",
      "4  competitions/cifar-10/train/45005.png    airplane\n",
      "                           filepath class\n",
      "0  competitions/cifar-10/test/1.png   cat\n",
      "1  competitions/cifar-10/test/2.png   cat\n",
      "2  competitions/cifar-10/test/3.png   cat\n",
      "3  competitions/cifar-10/test/4.png   cat\n",
      "4  competitions/cifar-10/test/5.png   cat\n"
     ]
    }
   ],
   "source": [
    "# train_df = pd.DataFrame(train_labels_info)\n",
    "train_df = pd.DataFrame(train_labels_info[0:45000])\n",
    "valid_df = pd.DataFrame(train_labels_info[45000:])\n",
    "test_df = pd.DataFrame(test_csv_info)\n",
    "\n",
    "train_df.columns = ['filepath', 'class']\n",
    "valid_df.columns = ['filepath', 'class']\n",
    "test_df.columns = ['filepath', 'class']\n",
    "\n",
    "print(train_df.head())\n",
    "print(valid_df.head())\n",
    "print(test_df.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:44.158498Z",
     "start_time": "2025-01-21T08:01:43.217782Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:34:38.988290Z",
     "iopub.status.busy": "2025-01-23T08:34:38.987947Z",
     "iopub.status.idle": "2025-01-23T08:34:38.996139Z",
     "shell.execute_reply": "2025-01-23T08:34:38.995619Z",
     "shell.execute_reply.started": "2025-01-23T08:34:38.988267Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "from torchvision import transforms\n",
    "\n",
    "class Cifar10Dataset(Dataset):\n",
    "    df_map = {\n",
    "        \"train\": train_df,\n",
    "        \"eval\": valid_df,\n",
    "        \"test\": test_df\n",
    "    }\n",
    "    label_to_idx = {label: idx for idx, label in enumerate(class_names)}\n",
    "    idx_to_label = {idx: label for idx, label in enumerate(class_names)}\n",
    "    def __init__(self, mode, transform=None):\n",
    "        self.df = self.df_map.get(mode, None)\n",
    "        if self.df is None:\n",
    "            raise ValueError(\"mode should be one of train, val, test, but got {}\".format(mode))\n",
    "\n",
    "        self.transform = transform\n",
    "        \n",
    "    def __getitem__(self, index):\n",
    "        img_path, label = self.df.iloc[index]\n",
    "        img = Image.open(img_path).convert('RGB')\n",
    "        # # img 转换为 channel first\n",
    "        # img = img.transpose((2, 0, 1))\n",
    "        # transform\n",
    "        img = self.transform(img)\n",
    "        # label 转换为 idx\n",
    "        label = self.label_to_idx[label]\n",
    "        return img, label\n",
    "    \n",
    "    def __len__(self):\n",
    "        return self.df.shape[0]\n",
    "    \n",
    "IMAGE_SIZE = 32\n",
    "mean, std = [0.4914, 0.4822, 0.4465], [0.247, 0.243, 0.261]\n",
    "\n",
    "transforms_train = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        # random rotation 40\n",
    "        transforms.RandomRotation(40),\n",
    "        # horizaontal flip\n",
    "        transforms.RandomHorizontalFlip(),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "transforms_eval = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "train_ds = Cifar10Dataset(\"train\", transforms_train)\n",
    "eval_ds = Cifar10Dataset(\"eval\", transforms_eval) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:44.162011Z",
     "start_time": "2025-01-21T08:01:44.158498Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:43:12.957975Z",
     "iopub.status.busy": "2025-01-23T08:43:12.957618Z",
     "iopub.status.idle": "2025-01-23T08:43:12.961287Z",
     "shell.execute_reply": "2025-01-23T08:43:12.960813Z",
     "shell.execute_reply.started": "2025-01-23T08:43:12.957952Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "batch_size = 64\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)   \n",
    "eval_dl = DataLoader(eval_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:01:44.173034Z",
     "start_time": "2025-01-21T08:01:44.162011Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-21T08:17:50.080075Z",
     "iopub.status.busy": "2025-01-21T08:17:50.079910Z",
     "iopub.status.idle": "2025-01-21T08:17:50.082683Z",
     "shell.execute_reply": "2025-01-21T08:17:50.082228Z",
     "shell.execute_reply.started": "2025-01-21T08:17:50.080057Z"
    }
   },
   "outputs": [],
   "source": [
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "# def cal_mean_std(ds):\n",
    "#     mean = 0.\n",
    "#     std = 0.\n",
    "#     for img, _ in ds:\n",
    "#         mean += img.mean(dim=(1, 2))\n",
    "#         std += img.std(dim=(1, 2))\n",
    "#     mean /= len(ds)\n",
    "#     std /= len(ds)\n",
    "#     return mean, std\n",
    "#\n",
    "# # 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:07:02.978303Z",
     "start_time": "2025-01-21T08:07:02.972820Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:41:51.897321Z",
     "iopub.status.busy": "2025-01-23T08:41:51.896977Z",
     "iopub.status.idle": "2025-01-23T08:41:51.904345Z",
     "shell.execute_reply": "2025-01-23T08:41:51.903714Z",
     "shell.execute_reply.started": "2025-01-23T08:41:51.897297Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class InceptionBolck(nn.Module):\n",
    "    #output_channel_for_each_path: 1*1卷积输出通道数，3*3卷积输出通道数，5*5卷积输出通道数，池化层输出通道数\n",
    "    def __init__(self, input_channels: int, output_channel_for_each_path: list[int]):\n",
    "        super(InceptionBolck, self).__init__()\n",
    "        self.conv1_1 = nn.Conv2d(\n",
    "            in_channels=input_channels, \n",
    "            out_channels=output_channel_for_each_path[0],\n",
    "            kernel_size=1, \n",
    "            padding=\"same\"\n",
    "            )\n",
    "        \n",
    "        self.conv3_3 = nn.Conv2d(\n",
    "            in_channels=input_channels, \n",
    "            out_channels=output_channel_for_each_path[1], \n",
    "            kernel_size=3, \n",
    "            padding=\"same\"\n",
    "            )\n",
    "        self.conv5_5 = nn.Conv2d(\n",
    "            in_channels=input_channels, \n",
    "            out_channels=output_channel_for_each_path[2], \n",
    "            kernel_size=5, \n",
    "            padding=\"same\"\n",
    "            ) # 5*5卷积核，要same，上下左右各补两圈0\n",
    "        self.max_pooling = nn.MaxPool2d(\n",
    "            kernel_size=2, \n",
    "            stride=2, \n",
    "            )\n",
    "        \n",
    "    def forward(self, x):\n",
    "        conv1_1 = F.relu(self.conv1_1(x))\n",
    "        conv3_3 = F.relu(self.conv3_3(x))\n",
    "        conv5_5 = F.relu(self.conv5_5(x))\n",
    "        max_pooling = self.max_pooling(x) # 最大池化，图像尺寸缩小一半\n",
    "        \n",
    "        max_pooling_shape = max_pooling.shape[1:] #最后3个维度，即通道、高、宽\n",
    "        input_shape = x.shape[1:] # 输入的通道、高、宽\n",
    "        width_padding = (input_shape[-2] - max_pooling_shape[-2]) // 2 # // 输入尺寸，减去池化尺寸，再除以2\n",
    "        height_padding = (input_shape[-1] - max_pooling_shape[-1]) // 2\n",
    "        padded_pooling = F.pad(\n",
    "            max_pooling, \n",
    "            [width_padding, width_padding, height_padding, height_padding]\n",
    "            ) # [left, right, top, bottom]，在每个维度上填充的长度，默认填充最后两个维度，即高和宽，填充0\n",
    "        concat_output = torch.cat(\n",
    "            [conv1_1, conv3_3, conv5_5, padded_pooling], \n",
    "            dim=1\n",
    "            ) # 在通道维度上拼接\n",
    "        return concat_output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:15:10.358796Z",
     "start_time": "2025-01-21T08:15:10.350873Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:41:53.436450Z",
     "iopub.status.busy": "2025-01-23T08:41:53.436097Z",
     "iopub.status.idle": "2025-01-23T08:41:53.451114Z",
     "shell.execute_reply": "2025-01-23T08:41:53.450514Z",
     "shell.execute_reply.started": "2025-01-23T08:41:53.436425Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             model.0.weight             paramerters num: 864\n",
      "              model.0.bias              paramerters num: 32\n",
      "         model.3.conv1_1.weight         paramerters num: 512\n",
      "          model.3.conv1_1.bias          paramerters num: 16\n",
      "         model.3.conv3_3.weight         paramerters num: 4608\n",
      "          model.3.conv3_3.bias          paramerters num: 16\n",
      "         model.3.conv5_5.weight         paramerters num: 12800\n",
      "          model.3.conv5_5.bias          paramerters num: 16\n",
      "         model.4.conv1_1.weight         paramerters num: 1280\n",
      "          model.4.conv1_1.bias          paramerters num: 16\n",
      "         model.4.conv3_3.weight         paramerters num: 11520\n",
      "          model.4.conv3_3.bias          paramerters num: 16\n",
      "         model.4.conv5_5.weight         paramerters num: 32000\n",
      "          model.4.conv5_5.bias          paramerters num: 16\n",
      "         model.6.conv1_1.weight         paramerters num: 2048\n",
      "          model.6.conv1_1.bias          paramerters num: 16\n",
      "         model.6.conv3_3.weight         paramerters num: 18432\n",
      "          model.6.conv3_3.bias          paramerters num: 16\n",
      "         model.6.conv5_5.weight         paramerters num: 51200\n",
      "          model.6.conv5_5.bias          paramerters num: 16\n",
      "         model.7.conv1_1.weight         paramerters num: 2816\n",
      "          model.7.conv1_1.bias          paramerters num: 16\n",
      "         model.7.conv3_3.weight         paramerters num: 25344\n",
      "          model.7.conv3_3.bias          paramerters num: 16\n",
      "         model.7.conv5_5.weight         paramerters num: 70400\n",
      "          model.7.conv5_5.bias          paramerters num: 16\n",
      "            model.10.weight             paramerters num: 35840\n",
      "             model.10.bias              paramerters num: 10\n"
     ]
    }
   ],
   "source": [
    "class InceptionNet(nn.Module):\n",
    "    def __init__(self, num_classes=10):\n",
    "        super(InceptionNet, self).__init__()\n",
    "        self.model = nn.Sequential(\n",
    "            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=\"same\"),\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=2),#16*16\n",
    "            InceptionBolck(input_channels=32, output_channel_for_each_path=[16, 16, 16]),#80*16*16\n",
    "            InceptionBolck(input_channels=80, output_channel_for_each_path=[16, 16, 16]),#128*16*16\n",
    "            nn.MaxPool2d(kernel_size=2, stride=2),#8*8\n",
    "            InceptionBolck(input_channels=128, output_channel_for_each_path=[16, 16, 16]),#176*8*8\n",
    "            InceptionBolck(input_channels=176, output_channel_for_each_path=[16, 16, 16]),#224*8*8\n",
    "            nn.MaxPool2d(kernel_size=2, stride=2),#224*4*4\n",
    "            nn.Flatten(),\n",
    "            nn.Linear(3584, num_classes)\n",
    "        )\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "                \n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "\n",
    "            \n",
    "for key, value in InceptionNet(len(class_names)).named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-21T08:15:01.892610Z",
     "start_time": "2025-01-21T08:15:01.887961Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-23T08:41:56.207812Z",
     "iopub.status.busy": "2025-01-23T08:41:56.207449Z",
     "iopub.status.idle": "2025-01-23T08:41:56.212170Z",
     "shell.execute_reply": "2025-01-23T08:41:56.211605Z",
     "shell.execute_reply.started": "2025-01-23T08:41:56.207786Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3584"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "224*4*4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-25T02:18:21.466720300Z",
     "start_time": "2024-07-25T02:18:21.440027700Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-23T08:41:57.397008Z",
     "iopub.status.busy": "2025-01-23T08:41:57.396658Z",
     "iopub.status.idle": "2025-01-23T08:41:57.406535Z",
     "shell.execute_reply": "2025-01-23T08:41:57.406038Z",
     "shell.execute_reply.started": "2025-01-23T08:41:57.396984Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total params: 269,898\n"
     ]
    }
   ],
   "source": [
    "#计算总参数量\n",
    "total_params = sum(p.numel() for p in InceptionNet(len(class_names)).parameters() if p.requires_grad)\n",
    "print(f\"Total params: {total_params:,}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-26T01:31:06.814529600Z",
     "start_time": "2024-07-26T01:31:06.152598300Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-23T08:41:59.063447Z",
     "iopub.status.busy": "2025-01-23T08:41:59.063090Z",
     "iopub.status.idle": "2025-01-23T08:41:59.500233Z",
     "shell.execute_reply": "2025-01-23T08:41:59.499703Z",
     "shell.execute_reply.started": "2025-01-23T08:41:59.063423Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/site-packages/torchvision/models/inception.py:43: FutureWarning: The default weight initialization of inception_v3 will be changed in future releases of torchvision. If you wish to keep the old behavior (which leads to long initialization times due to scipy/scipy#11299), please set init_weights=True.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Inception3(\n",
       "  (Conv2d_1a_3x3): BasicConv2d(\n",
       "    (conv): Conv2d(3, 32, kernel_size=(3, 3), stride=(2, 2), bias=False)\n",
       "    (bn): BatchNorm2d(32, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  )\n",
       "  (Conv2d_2a_3x3): BasicConv2d(\n",
       "    (conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), bias=False)\n",
       "    (bn): BatchNorm2d(32, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  )\n",
       "  (Conv2d_2b_3x3): BasicConv2d(\n",
       "    (conv): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "    (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  )\n",
       "  (maxpool1): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (Conv2d_3b_1x1): BasicConv2d(\n",
       "    (conv): Conv2d(64, 80, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "    (bn): BatchNorm2d(80, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  )\n",
       "  (Conv2d_4a_3x3): BasicConv2d(\n",
       "    (conv): Conv2d(80, 192, kernel_size=(3, 3), stride=(1, 1), bias=False)\n",
       "    (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  )\n",
       "  (maxpool2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (Mixed_5b): InceptionA(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_1): BasicConv2d(\n",
       "      (conv): Conv2d(192, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(48, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_2): BasicConv2d(\n",
       "      (conv): Conv2d(48, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(192, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(32, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_5c): InceptionA(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_1): BasicConv2d(\n",
       "      (conv): Conv2d(256, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(48, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_2): BasicConv2d(\n",
       "      (conv): Conv2d(48, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_5d): InceptionA(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(288, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_1): BasicConv2d(\n",
       "      (conv): Conv2d(288, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(48, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch5x5_2): BasicConv2d(\n",
       "      (conv): Conv2d(48, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(288, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(288, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_6a): InceptionB(\n",
       "    (branch3x3): BasicConv2d(\n",
       "      (conv): Conv2d(288, 384, kernel_size=(3, 3), stride=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(288, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(64, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(96, 96, kernel_size=(3, 3), stride=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(96, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_6b): InceptionC(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_2): BasicConv2d(\n",
       "      (conv): Conv2d(128, 128, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_3): BasicConv2d(\n",
       "      (conv): Conv2d(128, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(128, 128, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(128, 128, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_4): BasicConv2d(\n",
       "      (conv): Conv2d(128, 128, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_5): BasicConv2d(\n",
       "      (conv): Conv2d(128, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_6c): InceptionC(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_2): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_3): BasicConv2d(\n",
       "      (conv): Conv2d(160, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_4): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_5): BasicConv2d(\n",
       "      (conv): Conv2d(160, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_6d): InceptionC(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_2): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_3): BasicConv2d(\n",
       "      (conv): Conv2d(160, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_4): BasicConv2d(\n",
       "      (conv): Conv2d(160, 160, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(160, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_5): BasicConv2d(\n",
       "      (conv): Conv2d(160, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_6e): InceptionC(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_2): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7_3): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_3): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_4): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7dbl_5): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (AuxLogits): InceptionAux(\n",
       "    (conv0): BasicConv2d(\n",
       "      (conv): Conv2d(768, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (conv1): BasicConv2d(\n",
       "      (conv): Conv2d(128, 768, kernel_size=(5, 5), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(768, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (fc): Linear(in_features=768, out_features=1000, bias=True)\n",
       "  )\n",
       "  (Mixed_7a): InceptionD(\n",
       "    (branch3x3_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_2): BasicConv2d(\n",
       "      (conv): Conv2d(192, 320, kernel_size=(3, 3), stride=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(320, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7x3_1): BasicConv2d(\n",
       "      (conv): Conv2d(768, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7x3_2): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(1, 7), stride=(1, 1), padding=(0, 3), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7x3_3): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(7, 1), stride=(1, 1), padding=(3, 0), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch7x7x3_4): BasicConv2d(\n",
       "      (conv): Conv2d(192, 192, kernel_size=(3, 3), stride=(2, 2), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_7b): InceptionE(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(1280, 320, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(320, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_1): BasicConv2d(\n",
       "      (conv): Conv2d(1280, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_2a): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(1, 3), stride=(1, 1), padding=(0, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_2b): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(3, 1), stride=(1, 1), padding=(1, 0), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(1280, 448, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(448, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(448, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3a): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(1, 3), stride=(1, 1), padding=(0, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3b): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(3, 1), stride=(1, 1), padding=(1, 0), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(1280, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (Mixed_7c): InceptionE(\n",
       "    (branch1x1): BasicConv2d(\n",
       "      (conv): Conv2d(2048, 320, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(320, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_1): BasicConv2d(\n",
       "      (conv): Conv2d(2048, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_2a): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(1, 3), stride=(1, 1), padding=(0, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3_2b): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(3, 1), stride=(1, 1), padding=(1, 0), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_1): BasicConv2d(\n",
       "      (conv): Conv2d(2048, 448, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(448, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_2): BasicConv2d(\n",
       "      (conv): Conv2d(448, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3a): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(1, 3), stride=(1, 1), padding=(0, 1), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch3x3dbl_3b): BasicConv2d(\n",
       "      (conv): Conv2d(384, 384, kernel_size=(3, 1), stride=(1, 1), padding=(1, 0), bias=False)\n",
       "      (bn): BatchNorm2d(384, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (branch_pool): BasicConv2d(\n",
       "      (conv): Conv2d(2048, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "      (bn): BatchNorm2d(192, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))\n",
       "  (dropout): Dropout(p=0.5, inplace=False)\n",
       "  (fc): Linear(in_features=2048, out_features=1000, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from torchvision.models import inception_v3\n",
    "model=inception_v3()\n",
    "model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-26T01:33:28.411511600Z",
     "start_time": "2024-07-26T01:33:28.399487300Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-21T08:17:50.546407Z",
     "iopub.status.busy": "2025-01-21T08:17:50.546152Z",
     "iopub.status.idle": "2025-01-21T08:17:50.550387Z",
     "shell.execute_reply": "2025-01-21T08:17:50.549859Z",
     "shell.execute_reply.started": "2025-01-21T08:17:50.546387Z"
    },
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total params: 27,161,264\n"
     ]
    }
   ],
   "source": [
    "total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "print(f\"Total params: {total_params:,}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-26T03:10:23.045400900Z",
     "start_time": "2024-07-26T03:10:21.357935400Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-21T08:17:50.551205Z",
     "iopub.status.busy": "2025-01-21T08:17:50.551023Z",
     "iopub.status.idle": "2025-01-21T08:18:24.369013Z",
     "shell.execute_reply": "2025-01-21T08:18:24.368508Z",
     "shell.execute_reply.started": "2025-01-21T08:17:50.551187Z"
    },
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/site-packages/torchvision/models/_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and may be removed in the future, please use 'weights' instead.\n",
      "  warnings.warn(\n",
      "/usr/local/lib/python3.10/site-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=VGG19_Weights.IMAGENET1K_V1`. You can also use `weights=VGG19_Weights.DEFAULT` to get the most up-to-date weights.\n",
      "  warnings.warn(msg)\n",
      "Downloading: \"https://download.pytorch.org/models/vgg19-dcbb9e9d.pth\" to /root/.cache/torch/hub/checkpoints/vgg19-dcbb9e9d.pth\n",
      "100%|██████████| 548M/548M [00:31<00:00, 18.3MB/s] \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "VGG(\n",
       "  (features): Sequential(\n",
       "    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (1): ReLU(inplace=True)\n",
       "    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (3): ReLU(inplace=True)\n",
       "    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (6): ReLU(inplace=True)\n",
       "    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (8): ReLU(inplace=True)\n",
       "    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (11): ReLU(inplace=True)\n",
       "    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (13): ReLU(inplace=True)\n",
       "    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (15): ReLU(inplace=True)\n",
       "    (16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (17): ReLU(inplace=True)\n",
       "    (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "    (19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (20): ReLU(inplace=True)\n",
       "    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (22): ReLU(inplace=True)\n",
       "    (23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (24): ReLU(inplace=True)\n",
       "    (25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (26): ReLU(inplace=True)\n",
       "    (27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (29): ReLU(inplace=True)\n",
       "    (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (31): ReLU(inplace=True)\n",
       "    (32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (33): ReLU(inplace=True)\n",
       "    (34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (35): ReLU(inplace=True)\n",
       "    (36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  )\n",
       "  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))\n",
       "  (classifier): Sequential(\n",
       "    (0): Linear(in_features=25088, out_features=4096, bias=True)\n",
       "    (1): ReLU(inplace=True)\n",
       "    (2): Dropout(p=0.5, inplace=False)\n",
       "    (3): Linear(in_features=4096, out_features=4096, bias=True)\n",
       "    (4): ReLU(inplace=True)\n",
       "    (5): Dropout(p=0.5, inplace=False)\n",
       "    (6): Linear(in_features=4096, out_features=1000, bias=True)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from torchvision.models import vgg19\n",
    "model=vgg19(pretrained=True)\n",
    "model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T07:32:25.732902700Z",
     "start_time": "2024-04-29T07:32:25.719926400Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:13.582213Z",
     "iopub.status.busy": "2025-01-23T08:42:13.581856Z",
     "iopub.status.idle": "2025-01-23T08:42:13.586094Z",
     "shell.execute_reply": "2025-01-23T08:42:13.585498Z",
     "shell.execute_reply.started": "2025-01-23T08:42:13.582188Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3584"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "224*4*4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T03:36:24.264691400Z",
     "start_time": "2024-07-24T03:36:24.252349Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:14.452132Z",
     "iopub.status.busy": "2025-01-23T08:42:14.451537Z",
     "iopub.status.idle": "2025-01-23T08:42:14.458395Z",
     "shell.execute_reply": "2025-01-23T08:42:14.457947Z",
     "shell.execute_reply.started": "2025-01-23T08:42:14.452106Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[[ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000, -0.2496, -0.6549,  1.2708,  1.7401,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000,  0.8339, -0.7820,  0.9250, -0.6323,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000, -0.8623, -2.2500, -1.3414, -1.6648,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000, -1.3422, -1.3698, -1.2569,  0.1465,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,\n",
       "            0.0000],\n",
       "          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,\n",
       "            0.0000]]]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#给F.pad写一个例子\n",
    "input_shape = (3, 8, 8)\n",
    "max_pooling_shape = (4, 4)\n",
    "width_padding = (8 - 4) // 2\n",
    "height_padding = (8 - 4) // 2\n",
    "padded_pooling = F.pad(\n",
    "    torch.randn(1, 1,4,4),\n",
    "    [width_padding, width_padding, height_padding, height_padding]\n",
    "    ) # [left, right, top, bottom]，在每个维度上填充的长度，默认填充最后两个维度，即高和宽，填充0\n",
    "padded_pooling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义损失函数和优化器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:17.765011Z",
     "iopub.status.busy": "2025-01-23T08:42:17.764420Z",
     "iopub.status.idle": "2025-01-23T08:42:17.767411Z",
     "shell.execute_reply": "2025-01-23T08:42:17.766930Z",
     "shell.execute_reply.started": "2025-01-23T08:42:17.764984Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:19.454545Z",
     "iopub.status.busy": "2025-01-23T08:42:19.454184Z",
     "iopub.status.idle": "2025-01-23T08:42:19.482118Z",
     "shell.execute_reply": "2025-01-23T08:42:19.481616Z",
     "shell.execute_reply.started": "2025-01-23T08:42:19.454520Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:25.165055Z",
     "iopub.status.busy": "2025-01-23T08:42:25.164570Z",
     "iopub.status.idle": "2025-01-23T08:42:25.225031Z",
     "shell.execute_reply": "2025-01-23T08:42:25.224511Z",
     "shell.execute_reply.started": "2025-01-23T08:42:25.165028Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:27.455366Z",
     "iopub.status.busy": "2025-01-23T08:42:27.454875Z",
     "iopub.status.idle": "2025-01-23T08:42:27.460784Z",
     "shell.execute_reply": "2025-01-23T08:42:27.460198Z",
     "shell.execute_reply.started": "2025-01-23T08:42:27.455338Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:42:29.244417Z",
     "iopub.status.busy": "2025-01-23T08:42:29.244057Z",
     "iopub.status.idle": "2025-01-23T08:42:29.248809Z",
     "shell.execute_reply": "2025-01-23T08:42:29.248312Z",
     "shell.execute_reply.started": "2025-01-23T08:42:29.244392Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:43:25.420184Z",
     "iopub.status.busy": "2025-01-23T08:43:25.419847Z",
     "iopub.status.idle": "2025-01-23T08:45:59.271841Z",
     "shell.execute_reply": "2025-01-23T08:45:59.271268Z",
     "shell.execute_reply.started": "2025-01-23T08:43:25.420161Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 14080/14080 [02:33<00:00, 91.67it/s, epoch=19] \n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "model = InceptionNet(num_classes=10)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用 Rmsprop\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001, alpha=0.9, eps=1e-07)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "    \n",
    "exp_name = \"inception_net\"\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/{exp_name}\")\n",
    "tensorboard_callback.draw_model(model, [1, 3, IMAGE_SIZE, IMAGE_SIZE])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/{exp_name}\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_dl, \n",
    "    eval_dl, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:47:00.700407Z",
     "iopub.status.busy": "2025-01-23T08:47:00.700022Z",
     "iopub.status.idle": "2025-01-23T08:47:00.961543Z",
     "shell.execute_reply": "2025-01-23T08:47:00.961031Z",
     "shell.execute_reply.started": "2025-01-23T08:47:00.700381Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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fPzxx7Db7XjjjTc6bfydzeLFi3HjjTfiuuuuw8iRI/HUU0/B7XZjyZIlMbdfvXo1pk+fjquuugpVVVWYPXs2rrzySqxbt66TR969SPb+WL16ddT9sX///g4b12effYZp06bhlltuwcknn4zBgwdjz5492s8LCgpQVVWFlStXxtx/zJgxOHr0KHbt2tVhYyTaRlAdoIBAAojoWk58B8ieD5njwckSEPAA7qKuHhFBEF1IVVUVPv/8c+zfvx/5+flxP30eMmQIXn/9dVx44YXgOA6/+c1vOjVE4Kc//SkmTZqE+++/H5dffjnWrFmDv/zlL3jiiScAAG+//Tb27t2LGTNmoKSkBEuXLoUkSRg2bBg+//xzrFy5ErNnz0Z5eTlWrVqF2tpajBgxotPG35mEQiFs2LABCxcu1B7jeR7nnHMO1qxZE3OfadOm4cUXX8S6deswefJk7N27F0uXLsX3v//9mNsHg0EEg5HkKo/HAwAQBAGCIBi2FQQBsixDkqS41xe7lth23YUBAwbg888/x969e5Gfn69FXrNjYeMePHgwXn/9dZx//vngOA533XWX9nP98Zi/j3VOEp0nxuDBg/HCCy/g3XffxcCBA/Hiiy9i/fr1GDhwoLbvXXfdhVtuuQU9evTAueeei5aWFqxevRrz58/HjBkzMG3aNFx22WWaa7Vjxw5wHBe3/4gdjyAIXRaWwK4t8zXWnUk05qAqfFoDoW53TNl4roHcHXd7j/fEF0AcpwQhBJqAoKerR0MQRBdzxx134Nprr8XIkSPh9/vx3HPPxdxu8eLFuP766zFt2jSUl5fj5z//ORobGzttnKeccgr+/e9/46677sL999+PXr164b777sO8efMAAMXFxXj99ddxzz33IBAIYMiQIfjXv/6FUaNGYfv27fj444/x6KOPwuPxoF+/fnj44Ydx3nnnddr4O5O6ujqIoojKykrD45WVlVoTv5mrrroKdXV1OO2007S1bW6++Wb86le/irn9okWLDE34jGXLlsHtdhses1qt6NmzJ1pbW9ssCWtpaUn4887mhz/8IW655RaMHj0afr8fjz/+OABlnPpSvXvvvRfz58/HaaedhtLSUtx2221obGxEKBTSxKEkSQgEAtr3AOD3+w3fy7IctU0srrjiCqxbtw5XXHEFOI7Dt7/9bVx//fVYsWKFtu8ll1yCpqYm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e+6lS5dy7rnnkpKSQk5ODtdccw179+6N2aa+vp7bbruNrKwskpOT+fznP09hYWHMNseOHePKK6/E4/GQk5PDHXfcQTAYjNlm7dq1nHPOOTidTkaOHMny5cs75DU8+OCDKIrC7bff3u1jPnnyJF/5ylfIysrC7XYzceJENmzYYDyuqip33XUX/fv3x+12M3fuXPbv3x9zjLKyMm644QZSU1NJT0/n61//OjU1NTHbbNu2jQsuuACXy8WgQYN4+OGH2x1zKBTiF7/4BcOGDcPtdjNixAjuvfdezN4k3SHu9957j6uuuor8/HwUReG1116LeTyRMb7yyiuMGTMGl8vFxIkTWbFiRbviDgQC3HnnnUycOJGkpCTy8/O56aabOHXqVLeOO55bb70VRVF47LHHujxuofXIuenMkHOTnJtAzk2JjLvXnZfUXsyLL76oOhwO9emnn1Z37typ3nLLLWp6erpaWFiYkOefP3+++swzz6g7duxQt2zZoi5YsEAdPHiwWlNTY2xz6623qoMGDVLXrFmjbtiwQT3vvPPUWbNmGY8Hg0F1woQJ6ty5c9XNmzerK1asULOzs9UlS5YY2xw6dEj1eDzq4sWL1V27dqmPP/64arVa1ZUrV55R/OvXr1eHDh2qTpo0Sf3+97/frWMuKytThwwZon71q19VP/nkE/XQoUPqW2+9pR44cMDY5sEHH1TT0tLU1157Td26dav62c9+Vh02bJhaV1dnbHP55ZerkydPVj/++GP1/fffV0eOHKlef/31xuOVlZVqbm6uesMNN6g7duxQ//a3v6lut1v9wx/+0K6477//fjUrK0t9/fXX1cOHD6uvvPKKmpycrP72t7/tVnGvWLFC/dnPfqa++uqrKqD+85//jHk8UTF++OGHqtVqVR9++GF1165d6s9//nPVbrer27dvb3PcFRUV6ty5c9WXXnpJ3bNnj7pu3Tp1+vTp6tSpU2OO0d3iNvPqq6+qkydPVvPz89VHH320y+MWWoecm+TcJOemjolbzk2Ji7u3nZd6tQCaPn26ettttxm3Q6GQmp+fry5durRL4ikqKlIB9d1331VVVfuS2+129ZVXXjG22b17twqo69atU1VV+8JZLBa1oKDA2ObJJ59UU1NTVZ/Pp6qqqv74xz9Wx48fH/Nc1113nTp//vx2x1pdXa2OGjVKXb16tXrRRRcZ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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=100)  #横坐标是 steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:47:04.588499Z",
     "iopub.status.busy": "2025-01-23T08:47:04.588144Z",
     "iopub.status.idle": "2025-01-23T08:47:05.287945Z",
     "shell.execute_reply": "2025-01-23T08:47:05.287339Z",
     "shell.execute_reply.started": "2025-01-23T08:47:04.588473Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2416/3500857114.py:4: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
      "  model.load_state_dict(torch.load(f\"checkpoints/{exp_name}/best.ckpt\", map_location=\"cpu\"))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.8230\n",
      "accuracy: 0.7236\n"
     ]
    }
   ],
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/{exp_name}/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, eval_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 推理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-23T08:47:07.173104Z",
     "iopub.status.busy": "2025-01-23T08:47:07.172729Z",
     "iopub.status.idle": "2025-01-23T08:49:03.985120Z",
     "shell.execute_reply": "2025-01-23T08:49:03.984570Z",
     "shell.execute_reply.started": "2025-01-23T08:47:07.173077Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 4688/4688 [01:56<00:00, 40.14it/s]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>filepath</th>\n",
       "      <th>class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>competitions/cifar-10/test/1.png</td>\n",
       "      <td>deer</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>competitions/cifar-10/test/2.png</td>\n",
       "      <td>airplane</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>competitions/cifar-10/test/3.png</td>\n",
       "      <td>automobile</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>competitions/cifar-10/test/4.png</td>\n",
       "      <td>ship</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>competitions/cifar-10/test/5.png</td>\n",
       "      <td>bird</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           filepath       class\n",
       "0  competitions/cifar-10/test/1.png        deer\n",
       "1  competitions/cifar-10/test/2.png    airplane\n",
       "2  competitions/cifar-10/test/3.png  automobile\n",
       "3  competitions/cifar-10/test/4.png        ship\n",
       "4  competitions/cifar-10/test/5.png        bird"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# test_df\n",
    "test_ds = Cifar10Dataset(\"test\", transform=transforms_eval)\n",
    "test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, drop_last=False)\n",
    "\n",
    "preds_collect = []\n",
    "model.eval()\n",
    "for data, fake_label in tqdm(test_dl):\n",
    "    data = data.to(device=device)\n",
    "    logits = model(data)\n",
    "    preds = [test_ds.idx_to_label[idx] for idx in logits.argmax(axis=-1).cpu().tolist()]\n",
    "    preds_collect.extend(preds)\n",
    "    \n",
    "test_df[\"class\"] = preds_collect\n",
    "test_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-21T08:21:58.272012Z",
     "iopub.status.busy": "2025-01-21T08:21:58.271588Z",
     "iopub.status.idle": "2025-01-21T08:21:58.590533Z",
     "shell.execute_reply": "2025-01-21T08:21:58.589993Z",
     "shell.execute_reply.started": "2025-01-21T08:21:58.271992Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 导出 submission.csv\n",
    "test_df.to_csv(\"submission.csv\", index=False)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
